<?php

namespace app\common\command;

use app\common\service\TxService;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Db;
use think\facade\Log;

class CheckWithdrawalStatus extends Command
{
    // USDT 主网合约地址
    const USDT_CONTRACT = '0xdac17f958d2ee523a2206206994597c13d831ec7';

    // Transfer 事件签名
    const TRANSFER_EVENT = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
    // 平台热钱包地址（from）
    const HOT_WALLET_ADDRESS = '0xcEB4BcCf00EbF5B9E65732984331EFC3A776212D';

    protected function configure()
    {
        $this->setName('check_withdrawal_status')
            ->setDescription('轮询并更新用户提现USDT记录状态（基于链上交易哈希）');
    }

    protected function execute(Input $input, Output $output)
    {
        $output->writeln("[". date('Y-m-d H:i:s') ."] 开始执行提现状态检查任务...");

        // 获取所有待处理的提现记录（仅限 USDT 且有 tx_hash）
        $pendingList = Db::name('user_withdraw')
            ->where('status', 'pending')
            ->where('coin_type', 'usdt')
            ->whereNotNull('tx_hash')
            ->field('id, user_id, tx_hash, address, actual_amount, create_time')
            ->select()
            ->toArray();

        if (empty($pendingList)) {
            $output->writeln("✅ 暂无待确认的提现订单。");
            return 0;
        }

        $txService = new TxService();
        $updatedCount = 0;

        foreach ($pendingList as $item) {
            $output->writeln("🔍 检查提现单 #{$item['id']}，交易哈希: {$item['tx_hash']}");

            try {
                // 调用服务获取完整交易信息（含 receipt.logs）
                $txData = $txService->getTransaction($item['tx_hash']);

                if (empty($txData)) {
                    $output->writeln("⚠️  交易数据为空，稍后重试...");
                    continue;
                }

                // 🔐 严谨判断：是否成功完成 USDT 转账
//                $isSuccess = $this->verifyUsdtTransfer($txData, $item['address'], $item['actual_amount']);
                $isSuccess = false;

                if($txData['success'] && strtolower($txData['from']) == $item['address']) {
                    $isSuccess = true;
                }

                if ($isSuccess) {
                    // ✅ 成功：用户收到 USDT
                    Db::name('user_withdraw')->where('id', $item['id'])->update([
                        'status' => 'success',
                        'update_time' => time(),
                        'remark' => '链上确认: USDT 转账成功',
                    ]);
                    $output->writeln("✅ 提现 #{$item['id']} 已成功到账！");
                    $updatedCount++;
                } else {
                    // ❌ 失败：交易成功但未转账 USDT（或金额/地址不匹配）
//                    Db::name('user_withdraw')->where('id', $item['id'])->update([
//                        'status' => 'failed',
//                        'update_time' => time(),
//                        'remark' => '链上失败: 未检测到有效的 USDT 转账记录',
//                    ]);
                    $output->writeln("❌ 提现 #{$item['id']} 失败：未找到匹配的 USDT 转账");
                    $updatedCount++;
                }

            } catch (\InvalidArgumentException $e) {
                Log::error('TxHash 格式错误', ['id' => $item['id'], 'tx_hash' => $item['tx_hash']]);
                $output->writeln("⚠️  提现 #{$item['id']} tx_hash 格式异常");

            } catch (\think\exception\HttpException $e) {
                if ($e->getCode() === 404) {
                    $output->writeln("🟡 链上未找到交易 #{$item['id']}，可能还未确认");
                } else {
                    $output->writeln("🌐 请求失败 (HTTP {$e->getCode()})，稍后重试...");
                    Log::warning('TxService HTTP Error', ['code' => $e->getCode(), 'id' => $item['id']]);
                }

            } catch (\Exception $e) {
                Log::error('检查提现状态异常', [
                    'id' => $item['id'],
                    'error' => $e->getMessage()
                ]);
                $output->writeln("❗️ 处理 #{$item['id']} 时出错: " . $e->getMessage());
            }

            usleep(200000); // 0.2秒
        }

        $output->writeln("✅ 任务完成！共处理 " . count($pendingList) . " 条，更新状态 {$updatedCount} 条。");
        return 0;
    }

    /**
     * 严谨验证 USDT 转账是否成功
     *
     * @param array $txData 交易数据（含 receipt.logs）
     * @param string $toAddress 用户提现地址
     * @param float $expectedAmount 预期到账金额（USDT）
     * @return bool
     */
    private function verifyUsdtTransfer(array $txData, string $toAddress, float $expectedAmount): bool
    {
        // 1. 交易必须成功
        if (empty($txData['status']) || $txData['status'] != 1) {
            return false;
        }

        // 2. 必须有 logs
        if (empty($txData['receipt']['logs'])) {
            return false;
        }

        foreach ($txData['receipt']['logs'] as $log) {
            // 3. 合约地址必须是 USDT
//            if (!isset($log['address']) || strtolower($log['address']) !== strtolower(self::USDT_CONTRACT)) {
//                continue;
//            }

//            // 4. 必须是 Transfer 事件
//            if (empty($log['topics'][0]) || strtolower($log['topics'][0]) !== strtolower(self::TRANSFER_EVENT)) {
//                continue;
//            }

            // 5. to 地址必须匹配
            if (empty($log['topics'][2])) {
                continue;
            }
            $logTo = '0x' . substr($log['topics'][2], 26); // 取后40字符
            if (strtolower($logTo) !== strtolower($toAddress)) {
                continue;
            }

            // 6. 【可选】金额必须匹配（防止打错金额）
            if (!empty($log['data'])) {
                $logValue = hexdec(ltrim($log['data'], '0x')); // 单位：USDT wei (1e6)
                $expectedWei = (int)($expectedAmount * 1000000);
                if ($logValue != $expectedWei) {
                    return false; // 金额不匹配
                }
            }

            // 所有条件满足
            return true;
        }

        return false;
    }
}